/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.arg.deploy.core.hibernate;

import com.arg.deploy.bean.ErrorItem;
import com.arg.deploy.bean.Tag;
import com.arg.deploy.bean.TagLookupCatalog;
import com.arg.deploy.bean.User;
import com.arg.deploy.bean.ValidateBean;
import com.arg.deploy.common.DateUtil;
import com.arg.deploy.core.common.CoreContent;
import static com.arg.deploy.core.common.CoreContent.VALUE;
import com.arg.deploy.core.common.TransactionalProcessor;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

/**
 *
 * @author sorasaks
 */
public class TagCore extends CoreContent {

    private static final Logger LOG = Logger.getLogger(TagCore.class);

    public static Boolean remove(final Tag tag) {
        final HashMap param = new HashMap();
        try {
            new TransactionalProcessor() {
                @Override
                public void process(Session session, Transaction tx) throws Exception {
                    session.delete(tag);
                    param.put(VALUE, Boolean.TRUE);
                }
            }.process();
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
            param.put(VALUE, Boolean.FALSE);
        }

        return (Boolean) param.get(VALUE);
    }

    public static Boolean removeList(final List<Tag> tagList) {
        final HashMap param = new HashMap();
        try {
            new TransactionalProcessor() {
                @Override
                public void process(Session session, Transaction tx) throws Exception {
                    for (Tag tag : tagList) {
                        session.delete(tag);
                    }
                    param.put(VALUE, Boolean.TRUE);
                }
            }.process();
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
            param.put(VALUE, Boolean.FALSE);
        }

        return (Boolean) param.get(VALUE);
    }

    public static Boolean save(final Tag tag, final User user) {
        final HashMap param = new HashMap();
        try {
            new TransactionalProcessor() {
                @Override
                public void process(Session session, Transaction tx) throws Exception {
                    if (tag.getId() == null) {
                        Criteria criteria = session.createCriteria(Tag.class);
                        criteria.add(Restrictions.eq("path", tag.getPath()));
                        criteria.add(Restrictions.eq("revision", tag.getRevision()));
                        criteria.setMaxResults(1);

                        if (criteria.uniqueResult() == null) {
                            tag.setCreateBy(user);
                            session.saveOrUpdate(tag);
                        }
                    } else {
                        session.saveOrUpdate(tag);
                    }

                    param.put(VALUE, Boolean.TRUE);
                }
            }.process();
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
            param.put(VALUE, Boolean.FALSE);
        }

        return (Boolean) param.get(VALUE);
    }

    public static ValidateBean save(final Tag tag, final String username) {
        final HashMap param = new HashMap();
        final ValidateBean validate = new ValidateBean();
        try {
            new TransactionalProcessor() {
                @Override
                public void process(Session session, Transaction tx) throws Exception {
                    Criteria criteriaUser = session.createCriteria(User.class);
                    criteriaUser.add(Restrictions.eq("username", username));
                    criteriaUser.setMaxResults(1);
                    User user = (User) criteriaUser.uniqueResult();

                    if (user == null) {
                        List<ErrorItem> errorList = new ArrayList<ErrorItem>();
                        ErrorItem error = new ErrorItem();
                        error.setMessage(username + " isn't exists.");
                        errorList.add(error);
                        validate.setStatus(Boolean.FALSE);
                        validate.setErrorList(errorList);
                        param.put(VALUE, validate);
                        return;
                    }

                    if (tag.getId() == null) {
                        session.flush();
                        Criteria criteria = session.createCriteria(Tag.class);
                        criteria.add(Restrictions.eq("path", tag.getPath()));
                        criteria.add(Restrictions.eq("revision", tag.getRevision()));
                        criteria.setMaxResults(1);

                        if (criteria.uniqueResult() == null) {
                            tag.setCreateBy(user);
                            session.saveOrUpdate(tag);
                        }
                    } else {
                        session.saveOrUpdate(tag);
                    }

                    validate.setStatus(Boolean.TRUE);
                    validate.setErrorList(new ArrayList<ErrorItem>());
                    param.put(VALUE, validate);
                }
            }.process();
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
            validate.setStatus(Boolean.FALSE);
            validate.setErrorList(new ArrayList<ErrorItem>());
            param.put(VALUE, validate);
        }

        return (ValidateBean) param.get(VALUE);
    }

    public static ValidateBean saveList(final List<Tag> tagList, final User userByLogin) {
        final HashMap param = new HashMap();
        final ValidateBean validate = new ValidateBean();
        try {
            new TransactionalProcessor() {
                @Override
                public void process(Session session, Transaction tx) throws Exception {
                    List<Tag> saveList = new ArrayList<Tag>();
                    List<ErrorItem> errorList = new ArrayList<ErrorItem>();
                    for (Tag tag : tagList) {
                        Criteria criteriaUser = session.createCriteria(User.class);
                        criteriaUser.add(Restrictions.eq("username", tag.getUsername()));
                        criteriaUser.setMaxResults(1);
                        User user = (User) criteriaUser.uniqueResult();

                        if (user == null) {
                            ErrorItem error = new ErrorItem();
                            error.setMessage(tag.getUsername() + " isn't exists.");
                            errorList.add(error);
                            validate.setStatus(Boolean.FALSE);
                            validate.setErrorList(errorList);
                            param.put(VALUE, validate);
                            return;
                        }

                        tag.setUser(user);
                        tag.setCreateBy(userByLogin);

                        if (tag.getId() == null) {
                            session.flush();
                            Criteria criteria = session.createCriteria(Tag.class);
                            criteria.add(Restrictions.eq("path", tag.getPath()));
                            criteria.add(Restrictions.eq("revision", tag.getRevision()));
                            criteria.setMaxResults(1);
                            if (criteria.uniqueResult() == null) {
                                saveList.add(tag);
                            }
                        } else {
                            saveList.add(tag);
                        }
                        session.flush();
                    }

                    if (errorList.size() > 0) {
                        validate.setStatus(Boolean.FALSE);
                        validate.setErrorList(errorList);
                    } else {
                        for (Tag tag : saveList) {
                            session.saveOrUpdate(tag);
                        }
                        validate.setStatus(Boolean.TRUE);
                        validate.setErrorList(new ArrayList<ErrorItem>());
                    }

                    param.put(VALUE, validate);
                }
            }.process();
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
            validate.setStatus(Boolean.FALSE);
            validate.setErrorList(new ArrayList<ErrorItem>());
            param.put(VALUE, validate);
        }

        return (ValidateBean) param.get(VALUE);
    }

    public static ValidateBean saveList(final List<Tag> tagList, final TagLookupCatalog catalog, final String username, final String issue, final User userByLogin) {
        final HashMap param = new HashMap();
        final ValidateBean validate = new ValidateBean();
        try {
            new TransactionalProcessor() {
                @Override
                public void process(Session session, Transaction tx) throws Exception {
                    List<Tag> saveList = new ArrayList<Tag>();
                    List<ErrorItem> errorList = new ArrayList<ErrorItem>();
                    for (Tag tag : tagList) {
                        Criteria criteriaUser = session.createCriteria(User.class);
                        criteriaUser.add(Restrictions.eq("username", username));
                        criteriaUser.setMaxResults(1);
                        User user = (User) criteriaUser.uniqueResult();

                        if (user == null) {
                            ErrorItem error = new ErrorItem();
                            error.setMessage(username + " isn't exists.");
                            errorList.add(error);
                            validate.setStatus(Boolean.FALSE);
                            validate.setErrorList(errorList);
                            param.put(VALUE, validate);
                            return;
                        }

                        tag.setTag(catalog);
                        tag.setIssue(issue);
                        tag.setUser(user);
                        tag.setCreateBy(userByLogin);
                        tag.setCreateDate(new Date());

                        if (tag.getId() == null) {
                            session.flush();
                            Criteria criteria = session.createCriteria(Tag.class);
                            criteria.add(Restrictions.eq("path", tag.getPath().trim()));
                            criteria.add(Restrictions.eq("revision", tag.getRevision().trim()));
                            criteria.add(Restrictions.ge("createDate", DateUtil.getDateMinTime(new Date(), Locale.US)));
                            criteria.add(Restrictions.le("createDate", DateUtil.getDateMaxTime(new Date(), Locale.US)));
                            criteria.setMaxResults(1);
                            if (criteria.uniqueResult() == null) {
                                saveList.add(tag);
                            }
                        } else {
                            saveList.add(tag);
                        }
                        session.flush();
                    }

                    if (errorList.size() > 0) {
                        validate.setStatus(Boolean.FALSE);
                        validate.setErrorList(errorList);
                    } else {
                        for (Tag tag : saveList) {
                            session.saveOrUpdate(tag);
                        }
                        validate.setStatus(Boolean.TRUE);
                        validate.setErrorList(new ArrayList<ErrorItem>());
                    }

                    param.put(VALUE, validate);
                }
            }.process();
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
            validate.setStatus(Boolean.FALSE);
            validate.setErrorList(new ArrayList<ErrorItem>());
            param.put(VALUE, validate);
        }

        return (ValidateBean) param.get(VALUE);
    }

    public static List<Tag> getTag(final String issue,
            final User user,
            final TagLookupCatalog catalog,
            final Date startDate,
            final Date endDate) {
        final HashMap param = new HashMap();
        try {
            new TransactionalProcessor() {
                @Override
                public void process(Session session, Transaction tx) throws Exception {
                    Criteria criteria = session.createCriteria(Tag.class);

                    if (!StringUtils.isEmpty(issue)) {
                        criteria.add(Restrictions.eq("issue", issue));
                    }

                    if (user != null) {
                        criteria.add(Restrictions.eq("createBy.id", user.getId()));
                    }

                    criteria.add(Restrictions.eq("tag.id", catalog.getId()));

                    if (startDate != null && endDate != null) {
                        criteria.add(Restrictions.ge("createDate", DateUtil.getDateMinTime(startDate, Locale.US)));
                        criteria.add(Restrictions.le("createDate", DateUtil.getDateMaxTime(endDate, Locale.US)));
                    } else {
                        criteria.add(Restrictions.ge("createDate", DateUtil.getDateMinTime(new Date(), Locale.US)));
                        criteria.add(Restrictions.le("createDate", DateUtil.getDateMaxTime(new Date(), Locale.US)));
                    }

                    criteria.addOrder(Order.asc("issue"));

                    param.put(VALUE, criteria.list());
                }
            }.process();
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
            param.put(VALUE, new ArrayList<Tag>());
        }

        return (List<Tag>) param.get(VALUE);
    }

    public static List<Tag> getTagByListIssue(final List<String> issue,
            final List<String> notIssue,
            final User user,
            final TagLookupCatalog catalog,
            final Date startDate,
            final Date endDate) {
        final HashMap param = new HashMap();
        try {
            new TransactionalProcessor() {
                @Override
                public void process(Session session, Transaction tx) throws Exception {
                    Criteria criteria = session.createCriteria(Tag.class);

                    if (issue != null && !issue.isEmpty()) {
                        criteria.add(Restrictions.in("issue", issue));
                    }

                    if (notIssue != null && !notIssue.isEmpty()) {
                        criteria.add(Restrictions.not(Restrictions.in("issue", notIssue)));
                    }

                    if (user != null) {
                        criteria.add(Restrictions.eq("createBy.id", user.getId()));
                    }

                    criteria.add(Restrictions.eq("tag.id", catalog.getId()));

                    if (startDate != null && endDate != null) {
                        criteria.add(Restrictions.ge("createDate", DateUtil.getDateMinTime(startDate, Locale.US)));
                        criteria.add(Restrictions.le("createDate", DateUtil.getDateMaxTime(endDate, Locale.US)));
                    } else {
                        criteria.add(Restrictions.ge("createDate", DateUtil.getDateMinTime(new Date(), Locale.US)));
                        criteria.add(Restrictions.le("createDate", DateUtil.getDateMaxTime(new Date(), Locale.US)));
                    }

                    criteria.addOrder(Order.asc("issue"));

                    param.put(VALUE, criteria.list());
                }
            }.process();
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
            param.put(VALUE, new ArrayList<Tag>());
        }

        return (List<Tag>) param.get(VALUE);
    }
}
